package desgin.pattern.other.reactor;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;

/**
 * Created by kai on 2015/6/28 0028.
 * 接受连接
 */
public class NioAcceptor extends Thread {

    private final Selector selector;
    private final ServerSocketChannel serverSocketChannel;
    private final int default_port = 2000;//监听端口
    private static int port;
    private NioProcessor nioProcessor;
    private long acceptCount;

    public NioAcceptor(int port) throws IOException {

        this.selector = Selector.open();
        this.serverSocketChannel = ServerSocketChannel.open();
        if (port == 0) {
            this.port = default_port;//传0表示用默认端口
        }
        serverSocketChannel.bind(new InetSocketAddress(port));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    }

    public void setProcessor(NioProcessor nioProcessor) {
        this.nioProcessor = nioProcessor;
    }

    @Override
    public void run() {
        final Selector selector = this.selector;
        for (; ; ) {
            try {
                System.out.println("等待连接...");
                selector.select(15000L);
                acceptCount++;
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                for (SelectionKey key : selectionKeys) {
                    if (key.isValid() && key.isAcceptable()) {
                        accept();
                    } else {
                        key.cancel();
                        System.out.println("无效key,注销");
                    }

                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void accept() throws IOException {
        SocketChannel channel = serverSocketChannel.accept();
        channel.configureBlocking(false);
        NioConnection nioConnection = new NioConnection(channel);
        System.out.println("已经转交给reactor...");
        nioProcessor.postRegister(nioConnection);
    }
}
